#include "stdafx.h"
#include "net/HTTPFixedLengthStream.hpp"

NET_NAMESPACE_BEGIN

//
// CHTTPFixedLengthStreamBuf
//
CHTTPFixedLengthStreamBuf::CHTTPFixedLengthStreamBuf(CHTTPSession& session, ContentLength length, openmode mode)
	: HTTPBasicStreamBuf(CHTTPBufferAllocator::BUFFER_SIZE, mode),
	m_session(session),	
	m_length(length),
	m_count(0)
{
}

CHTTPFixedLengthStreamBuf::~CHTTPFixedLengthStreamBuf()
{
}

int CHTTPFixedLengthStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
	int n = 0;
	if (m_count < m_length)
	{
		if (m_count + length > m_length)
			length = static_cast<std::streamsize>(m_length - m_count);
		n = m_session.read(buffer, length);
		if (n > 0) m_count += n;
	}
	return n;
}

int CHTTPFixedLengthStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
	int n = 0;
	if (m_count < m_length)
	{
		if (m_count + length > m_length)
			length = static_cast<std::streamsize>(m_length - m_count);
		n = m_session.write(buffer, length);
		if (n > 0) m_count += n;
	}
	return n;
}


//
// CHTTPFixedLengthIOS
//
CHTTPFixedLengthIOS::CHTTPFixedLengthIOS(CHTTPSession& session, CHTTPFixedLengthStreamBuf::ContentLength length, CHTTPFixedLengthStreamBuf::openmode mode)
	: m_buf(session, length, mode)
{
	
}

CHTTPFixedLengthIOS::~CHTTPFixedLengthIOS()
{
	try
	{
		m_buf.sync();
	}
	catch (...)
	{
	}
}

CHTTPFixedLengthStreamBuf* CHTTPFixedLengthIOS::rdbuf()
{
	return &m_buf;
}


//
// CHTTPFixedLengthInputStream
//
CMemoryPool CHTTPFixedLengthInputStream::m_pool(sizeof(CHTTPFixedLengthInputStream));

CHTTPFixedLengthInputStream::CHTTPFixedLengthInputStream(CHTTPSession& session, CHTTPFixedLengthStreamBuf::ContentLength length)
	: CHTTPFixedLengthIOS(session, length, std::ios::in),
	std::istream(&m_buf)
{
}

CHTTPFixedLengthInputStream::~CHTTPFixedLengthInputStream()
{
}

void* CHTTPFixedLengthInputStream::operator new(std::size_t size)
{
	return m_pool.get();
}

void CHTTPFixedLengthInputStream::operator delete(void* ptr)
{
	try
	{
		m_pool.release(ptr);
	}
	catch (...)
	{
		jh_unexpected();
	}
}


//
// CHTTPFixedLengthOutputStream
//
CMemoryPool CHTTPFixedLengthOutputStream::m_pool(sizeof(CHTTPFixedLengthOutputStream));

CHTTPFixedLengthOutputStream::CHTTPFixedLengthOutputStream(CHTTPSession& session, CHTTPFixedLengthStreamBuf::ContentLength length)
	: CHTTPFixedLengthIOS(session, length, std::ios::out),
	std::ostream(&m_buf)
{
}

CHTTPFixedLengthOutputStream::~CHTTPFixedLengthOutputStream()
{
}

void* CHTTPFixedLengthOutputStream::operator new(std::size_t size)
{
	return m_pool.get();
}

void CHTTPFixedLengthOutputStream::operator delete(void* ptr)
{
	try
	{
		m_pool.release(ptr);
	}
	catch (...)
	{
		jh_unexpected();
	}
}

NET_NAMESPACE_END
